﻿/*
 * Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd. 2023-2023. All rights reserved.
 */

#include <QMimeData>
#include <QIcon>
#include <QMessageBox>
#include <QTranslator>
#include "BurnToolCommon/Global.h"
#include "BinFileModel.h"

namespace BurnDlg {

namespace {
    const int PIXMAP_WIDTH_SIZE_120 = 120;
    const int PIXMAP_HEIGHT_SIZE_120 = 120;
    const int COLUMN_COUNT_10 = 10;
}

BinFileModel::BinFileModel(QObject *parent)
    : QAbstractTableModel(parent),
      isCheckAble(true)
{
    const QStringList header1 = {"", tr("Name"), tr("Path"), tr("File Index"),
                                 tr("File Size"), tr("Burn Addr"), tr("Burn Size"),
                                 tr("Type"), "", ""};
    header = header1;
}

BinFileModel::~BinFileModel()
{
    ClearSource();
}

QVariant BinFileModel::headerData(int section, Qt::Orientation orientation, int role) const
{
    if (section == 0 && orientation == Qt::Horizontal) {
        int i = 0;
        for (; i < mapCheck.size(); i++) {
            if (!mapCheck[i]) {
                break;
            }
        }
        QIcon icon;
        if (i == mapCheck.size()) {
            QString pic = "ic_invert_selection_lined.png";
            icon.setThemeName(pic);
            QString strImage = QString(":/images/image/%1").arg(pic);
            icon.addPixmap(QPixmap(strImage).scaled(QSize(PIXMAP_WIDTH_SIZE_120, PIXMAP_HEIGHT_SIZE_120),
                Qt::KeepAspectRatio), QIcon::Normal);
            return icon;
        } else {
            QString pic = "ic_select_all_lined.png";
            icon.setThemeName(pic);
            QString strImage = QString(":/images/image/%1").arg(pic);
            icon.addPixmap(QPixmap(strImage).scaled(QSize(PIXMAP_WIDTH_SIZE_120, PIXMAP_HEIGHT_SIZE_120),
                Qt::KeepAspectRatio), QIcon::Normal);
            return icon;
        }
    }
    if (section != 0 && orientation == Qt::Horizontal && role == Qt::DisplayRole) {
        return header.at(section);
    }
    return QAbstractTableModel::headerData(section, orientation, role);
}

bool BinFileModel::setHeaderData(int section, Qt::Orientation orientation, const QVariant &value, int role)
{
    return QAbstractTableModel::setHeaderData(section, orientation, value, role);
}

QVariant BinFileModel::data(const QModelIndex &index, int role) const
{
    if (!index.isValid()) {
        return QVariant();
    }

    switch (role) {
        case Qt::DisplayRole:
        case Qt::EditRole:
            return ShowThisLine(index);
        case Qt::CheckStateRole:
            return CheckState(index);
        case Qt::DecorationRole:
            return ShowIcon(index);
        default:
            break;
    }

    return QVariant();
}

bool BinFileModel::setData(const QModelIndex &index, const QVariant &value, int role)
{
    if (!index.isValid()) {
        return false;
    }
    int nColumn = index.column();
    BIN_INFO info = mapBinFileInfo[index.row()];
    bool ret = false;
    switch (role) {
        case Qt::CheckStateRole: {
            ret = SetDataCheckState(index, value);
            break;
        }
        case Qt::DisplayRole:
        case Qt::EditRole: {
            if (nColumn == TABLEVIEW_COLUMN_NAME) {
                mapBinFileInfo[index.row()].fileName = value.toString();
            } else if (nColumn == TABLEVIEW_COLUMN_PAHT) {
                mapBinFileInfo[index.row()].path = value.toString();
            } else if (nColumn == TABLEVIEW_COLUMN_FILE_INDEX) {
                mapBinFileInfo[index.row()].fileIndex = value.toString();
            } else if (nColumn == TABLEVIEW_COLUMN_FILE_SIZE) {
                mapBinFileInfo[index.row()].fileSize = value.toString();
            } else if (nColumn == TABLEVIEW_COLUMN_BURN_ADDR) {
                mapBinFileInfo[index.row()].burnAddr = value.toString();
            } else if (nColumn == TABLEVIEW_COLUMN_BURN_SIZE) {
                mapBinFileInfo[index.row()].burnSize = value.toString();
            } else if (nColumn == TABLEVIEW_COLUMN_TYPE) {
                mapBinFileInfo[index.row()].type = static_cast<IMAGE_TYPE>(value.toInt());
            }
            emit dataChanged(index, index);
            ret = true;
            break;
        }
        default:
            break;
    }
    return ret;
}

Qt::ItemFlags BinFileModel::flags(const QModelIndex &index) const
{
    if (!index.isValid()) {
        return QAbstractItemModel::flags(index);
    }

    Qt::ItemFlags flags = Qt::ItemIsEnabled | Qt::ItemIsSelectable;
    if (index.column() == TABLEVIEW_COLUMN_CHECK) {
        flags |= Qt::ItemIsUserCheckable;
    }
    flags |= Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled;

    if (index.column() == TABLEVIEW_COLUMN_BURN_ADDR ||
        index.column() == TABLEVIEW_COLUMN_BURN_SIZE ||
        index.column() == TABLEVIEW_COLUMN_TYPE) {
        flags |= Qt::ItemIsEditable | Qt::ItemIsEnabled;
    }
    return flags;
}

int BinFileModel::rowCount(const QModelIndex &parent) const
{
    Q_UNUSED(parent);
    return mapBinFileInfo.count();
}

int BinFileModel::columnCount(const QModelIndex &parent) const
{
    Q_UNUSED(parent);
    return COLUMN_COUNT_10;
}

bool BinFileModel::SetDataCheckState(const QModelIndex &index, const QVariant &value)
{
    if (!isCheckAble) {
        return true;
    }
    int nColumn = index.column();
    int nRow = index.row();
    bool check = mapCheck[nRow];
    IMAGE_TYPE imageType = mapBinFileInfo[index.row()].type;
    if (nColumn == TABLEVIEW_COLUMN_CHECK) {
        if (imageType == IMAGE_TYPE::IMAGE_TYPE_RADIOCONFIG && !check) {
            int result = QMessageBox::information(nullptr, stringClass.GetInformation(),
                                                  stringClass.GetIdsString32971(), stringClass.GetOk(),
                                                  stringClass.GetCancel());
            if (result != 0) {
                return true;
            }
        }

        if (imageType == IMAGE_TYPE::IMAGE_TYPE_FLASHBOOT_3892 && !check) {
            int result = QMessageBox::information(nullptr, stringClass.GetInformation(),
                                                  stringClass.GetIdsString33277(), stringClass.GetOk(),
                                                  stringClass.GetCancel());
            if (result != 0) {
                return true;
            }
        }

        if (imageType == IMAGE_TYPE::IMAGE_TYPE_OTP && !check) {
            int result = QMessageBox::information(nullptr, stringClass.GetInformation(),
                                                  stringClass.GetIdsString33280(), stringClass.GetOk(),
                                                  stringClass.GetCancel());
            if (result != 0) {
                return true;
            }
        }
        check = (value.toInt() == Qt::Checked);
        mapCheck[index.row()] = check;
        emit dataChanged(index, index);
        emit headerDataChanged(Qt::Horizontal, 0, 0);
        return true;
    }
    return false;
}

QVariant BinFileModel::ShowThisLine(const QModelIndex &index) const
{
    const int row = index.row();
    const int column = index.column();
    if (column == TABLEVIEW_COLUMN_NAME) {
        return mapBinFileInfo[row].fileName;
    } else if (column == TABLEVIEW_COLUMN_PAHT) {
        return mapBinFileInfo[row].path;
    } else if (column == TABLEVIEW_COLUMN_FILE_INDEX) {
        return mapBinFileInfo[row].fileIndex;
    } else if (column == TABLEVIEW_COLUMN_FILE_SIZE) {
        return mapBinFileInfo[row].fileSize;
    } else if (column == TABLEVIEW_COLUMN_BURN_ADDR) {
        return mapBinFileInfo[row].burnAddr;
    } else if (column == TABLEVIEW_COLUMN_BURN_SIZE) {
        return mapBinFileInfo[row].burnSize;
    } else if (column == TABLEVIEW_COLUMN_TYPE) {
        return static_cast<int>(mapBinFileInfo[row].type);
    }

    return QVariant();
}

QVariant BinFileModel::CheckState(const QModelIndex &index) const
{
    const int row = index.row();
    const int column = index.column();
    if (column == TABLEVIEW_COLUMN_CHECK) {
        return mapCheck[row] ? Qt::Checked : Qt::Unchecked;
    }

    return QVariant();
}

QVariant BinFileModel::ShowIcon(const QModelIndex &index) const
{
    const int column = index.column();
    if (column == TABLEVIEW_COLUMN_ADD) {
        QIcon icon;
        QString pic = "ic_plus_lined.png";
        icon.setThemeName(pic);
        QString strImage = QString(":/images/image/%1").arg(pic);
        icon.addPixmap(QPixmap(strImage).scaled(QSize(PIXMAP_WIDTH_SIZE_120, PIXMAP_HEIGHT_SIZE_120),
            Qt::KeepAspectRatio), QIcon::Normal);
        return icon;
    } else if (column == TABLEVIEW_COLUMN_DELETE) {
        QIcon icon;
        QString pic = "ic_minus_lined.png";
        icon.setThemeName(pic);
        QString strImage = QString(":/images/image/%1").arg(pic);
        icon.addPixmap(QPixmap(strImage).scaled(QSize(PIXMAP_WIDTH_SIZE_120, PIXMAP_HEIGHT_SIZE_120),
            Qt::KeepAspectRatio), QIcon::Normal);
        return icon;
    }
    return QVariant();
}

void BinFileModel::FetchData(QMap<int, BIN_INFO> mapbinFileInfo)
{
    beginResetModel();
    this->mapBinFileInfo = mapbinFileInfo;
    endResetModel();
}

void BinFileModel::FetchData(QMap<int, bool> mapCheckData)
{
    beginResetModel();
    this->mapCheck = mapCheckData;
    endResetModel();
}

void BinFileModel::ClearSource()
{
    mapBinFileInfo.clear();
}

void BinFileModel::ClearData()
{
    beginResetModel();
    ClearSource();
    endResetModel();
}

QMap<int, BIN_INFO> BinFileModel::GetBinFileInfoData()
{
    return this->mapBinFileInfo;
}

bool BinFileModel::GetCheck(int index) const
{
    return mapCheck[index];
}

QMap<int, bool> BinFileModel::GetMapCheck()
{
    return mapCheck;
}

QString BinFileModel::GetValue(int row, int column) const
{
    if (column == TABLEVIEW_COLUMN_CHECK || column == TABLEVIEW_COLUMN_TYPE) {
        return "";
    }
    return index(row, column).data().toString();
}

IMAGE_TYPE BinFileModel::GetType(int row) const
{
    return static_cast<IMAGE_TYPE>(index(row, TABLEVIEW_COLUMN_TYPE).data().toInt());
}

QMap<int, BIN_INFO> BinFileModel::GetMapBinFileInfo()
{
    return mapBinFileInfo;
}

Qt::DropActions BinFileModel::supportedDragActions() const
{
    return Qt::MoveAction | QAbstractTableModel::supportedDragActions();
}

Qt::DropActions BinFileModel::supportedDropActions() const
{
    return Qt::MoveAction | QAbstractTableModel::supportedDropActions();
}

QMimeData *BinFileModel::mimeData(const QModelIndexList &indexes) const
{
    QMimeData *mimedata = QAbstractTableModel::mimeData(indexes);
    if (mimedata != nullptr) {
        mimedata->setData("row", QByteArray::number(indexes.at(0).row()));
    }
    return mimedata;
}

bool BinFileModel::dropMimeData(const QMimeData *data, Qt::DropAction action, RRE_UNUSED int row,
                                RRE_UNUSED int column, const QModelIndex &parent)
{
    if (data == nullptr || action != Qt::MoveAction) {
        return false;
    }
    int dropRow = data->data("row").toInt();
    int currentRow = parent.row();

    QMap<int, BIN_INFO> map;
    QMap<int, bool> check;
    int j = 0;
    for (int i = 0; i < mapBinFileInfo.size(); i++) {
        if (i == dropRow) {
            continue;
        }
        if (i == currentRow) {
            map[j] = mapBinFileInfo[dropRow];
            check[j] = mapCheck[dropRow];
            j++;
            map[j] = mapBinFileInfo[i];
            check[j] = mapCheck[i];
            j++;
            continue;
        }
        map[j] = mapBinFileInfo[i];
        check[j] = mapCheck[i];
        j++;
    }
    mapBinFileInfo.clear();
    mapCheck.clear();
    mapBinFileInfo = map;
    mapCheck = check;
    beginResetModel();
    endResetModel();
    return true;
}

bool BinFileModel::insertRows(int row, int count, const QModelIndex &parent)
{
    if (count == 0) {
        return false;
    }
    beginInsertRows(parent, row, row + count - 1);
    endInsertRows();
    int size = mapBinFileInfo.size();
    for (int i = size - 1; i >= row + 1; i--) {
        mapBinFileInfo[i + count] = mapBinFileInfo[i];
        mapCheck[i + count] = mapCheck[i];
    }
    for (int i = 0; i < count; i++) {
        mapBinFileInfo[i + row + 1] = BIN_INFO();
        mapCheck[i + row + 1] = false;
    }
    return true;
}

bool BinFileModel::removeRows(int row, int count, const QModelIndex &parent)
{
    beginRemoveRows(parent, row, row + count - 1);
    endRemoveRows();
    int size = mapBinFileInfo.size();
    for (int i = row + 1; i < size; i++) {
        mapBinFileInfo[i - 1] = mapBinFileInfo[i];
        mapCheck[i - 1] = mapCheck[i];
    }

    mapBinFileInfo.remove(size - 1);
    return true;
}

void BinFileModel::SetEditableCheckbox(bool isEditable)
{
    this->isCheckAble = isEditable;
}

}
